###########################################################################
# $Id: dbManager.p 13 2009-04-17 10:30:44Z donbeave $
###########################################################################

@CLASS
dbManager

@USE
pf/types/pfClass.p
db/models/dbSchema.p
db/models/dbTable.p
labour/tests/labourAssert.p

@OPTIONS
locals

#----- Constructor -----

@create[hshConfig]
## aOptions.sql
## aOptions.sqlConnectString[$MAIN:SQL.connect-string]
## aOptions.sqlOptions
  ^pfClass:cleanMethodArgument[]

  $self._createOptions[$aOptions]

  ^if(def $hshConfig.sql && $hshConfig.sql is pfSQL){
    $self._sql[$hshConfig.sql]
  }{
     $self._sql[]
   }

#----- Public -----

@useSchema[strName]
  ^pfClass:_abstractMethod[]

@getSchemas[]
  ^pfClass:_abstractMethod[]

@getTables[strSchema]
  ^pfClass:_abstractMethod[]

@getTableFields[strTable;strSchema]
  ^pfClass:_abstractMethod[]

#---- Private -----

@_createSchemaItem[strName]
  ^labourAssert:required[strName;string]

  $result[^dbSchema::create[
    $.manager[$self]
    $.name[$strName]
  ]]

@_createTableItem[strName]
  ^labourAssert:required[strName;string]

  $result[^dbTable::create[
    $.manager[$self]
    $.name[$strName]
  ]]

@_createField[strType;hshData]
  ^labourAssert:required[strType;string]

  ^switch[^strType.upper[]]{
    ^case[INT;TINYINT;BIGINT;DECIMAL;FLOAT]{
      $sClass[dbNumberField]
    }
    ^case[CHAR;VARCHAR;TEXT;LONGTEXT]{
      $sClass[dbStringField]
    }
    ^case[DATETIME;TIMESTAMP]{
      $sClass[dbDateTimeField]
    }
    ^case[DEFAULT]{
      ^pfAssert:fail[Type "^strType.upper[]" is not supported.]
    }
  }

  ^use[db/models/fields/${sClass}.p]

  $hshData.manager[$self]

# определяем поле объекта, т.к. локальная переменная hshData не доступна из process
  $self.__fieldData[$hshData]
  ^__fieldData.add[
    $.type[^strType.upper[]]
  ]

  ^process{
    ^$__item[^^${sClass}::create[^$__fieldData]]
  }

  $result[$__item]

# очищаем временные поля
  $self.__fieldData[]
  $self.__item[]

#----- Properties -----

@GET_CSQL[]
  ^if(!def $_sql){
    $_sql[^sqlFactory[^if(def $_createOptions.sqlConnectString){$_createOptions.sqlConnectString}{$MAIN:SQL.connect-string};$_createOptions.sqlOptions]]
  }
  $result[$_sql]

#----- Fabriques -----

@sqlFactory[aConnectString;aSqlOptions]
# Возвращает sql-объект исходя из $MAIN:SQL.connect-string
# Проверка на правильность строки не производится
  ^switch[^aConnectString.left(^aConnectString.pos[://])]{
    ^case[mysql]{
      ^use[pf/sql/pfMySQL.p]
      $result[^pfMySQL::create[$aConnectString;$aSqlOptions]]
    }
    ^case[DEFAULT]{
      ^pfAssert:fail[dbManager.sqlFactory. Bad connect-string.]
    }
  }